///////////////////////////////////////////////////////////////////////////////////////////////////
/// \file formic/matrix_actor.h
///
/// \brief   header file for the matrix actor class
///
///////////////////////////////////////////////////////////////////////////////////////////////////

#ifndef FORMIC_MATRIX_ACTOR_HEADER
#define FORMIC_MATRIX_ACTOR_HEADER

#include<string>

#include<formic/exception.h>

namespace formic {

  ///////////////////////////////////////////////////////////////////////////////////////////////////
  /// \brief  Base class for operating by a matrix A.
  ///
  ///////////////////////////////////////////////////////////////////////////////////////////////////
  template<class S> class MatrixActor {

    private:

      // function to throw an error if a function is not implemented by a child
      void not_implemented(const std::string & func_name) {
        throw formic::Exception("the %s function is not implemented for the %s class") % func_name % this->class_name();
      }

    public:

      // function to return the name of the child class
      virtual std::string class_name() = 0;

      // function to perform y = A d
      virtual void operate(const int n, S * const d, S * const y, const int myrank, const int tid) {
        this->not_implemented("operate");
      }

      // function to perform y = A^(-1) d
      virtual void operate_inv(const int n, S * const d, S * const y, const int myrank, const int tid) {
        this->not_implemented("operate_inv");
      }

      // make destructor virtual so that base pointers will call child destructors on deletion
      virtual ~MatrixActor() {}

  };

} // end namespace formic

#endif
